package net.sf.calibur.transport.message;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;

import net.sf.calibur.msgbuf.Command;
import net.sf.calibur.msgbuf.CommandFactory;
import net.sf.calibur.msgbuf.MessageBean;

public class CommandMessage extends Message {
	/** MessageBeanFactory */
	private CommandFactory commandFactory;

	/** command定义 */
	private Command command;

	/** 报文头 */
	private MessageHead head;

	public CommandMessage(MessageHead head, CommandFactory factory) {
		super(Message.MT_APPLICATION);
		this.head = head;
		this.commandFactory = factory;
	}
	
	public CommandMessage(CommandFactory factory, Command command) {
		super(Message.MT_APPLICATION);
		this.commandFactory = factory;
		this.command = command;
	}

	public Command createCommand(int commandId) throws Exception {
		command = commandFactory.getCommand(commandId);
		return command;
	}

	@Override
	public String toString() {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);

		pw.println("Sequence: " + getSequence());
		pw.println("Client Timestamp: " + getClientTimestamp());
		pw.println("Command: " + command.toString());
		return sw.toString();
	}

	public long getClientTimestamp() {
		return head == null ? 0L : head.getClientTimestamp();
	}

	@Override
	public void serialize(OutputStream output) throws Exception {
		DataOutputStream dos = new DataOutputStream(output);
		dos.writeShort(- command.getId());
		command.serializeOutputArgument(output);
	}

	@Override
	public void deserialize(InputStream input) throws Exception {
		DataInputStream dis = new DataInputStream(input);
		int commandId = dis.readShort();
		command = commandFactory.getCommand(commandId);
		command.deserializeInputArgument(input);
	}

	public int getCommandId() {
		return command.getId();
	}

	public Command getCommand() {
		return command;
	}
	
	public MessageBean getInput() {
		return command.getInput().getMessageBean();
	}
	
	public MessageBean getOutput() {
		return command.getOutput().getMessageBean();
	}
	
	@Override
	public void release() {
		command.getInput().clear();
		command.getOutput().clear();
	}
}
